home *** CD-ROM | disk | FTP | other *** search
/ ADA Programming Guide / ADA Programming Guide.iso / ada_gwu / adacomp.c < prev    next >
C/C++ Source or Header  |  1996-01-30  |  12KB  |  476 lines

  1. /*
  2.  * Copyright (C) 1985-1992  New York University
  3.  * 
  4.  * This file is part of the Ada/Ed-C system.  See the Ada/Ed README file for
  5.  * warranty (none) and distribution info and also the GNU General Public
  6.  * License for more details.
  7.  
  8.  */
  9.  
  10. #include <stdlib.h>
  11. #include <stdio.h>
  12. #include <ctype.h>
  13. #include <string.h>
  14. #ifdef __GNUG__
  15. #define WAITPARM (int*)
  16. #else
  17. #define WAITPARM (union wait*)
  18. #endif
  19. #include "config.h"
  20. #include "adamrgp.h"
  21. #include "miscp.h"
  22.  
  23. #include <sys/types.h>
  24. #ifdef IBM_PC
  25. #include <fcntl.h>
  26. #include <process.h>
  27. #else
  28. #include <sys/file.h>
  29. #endif
  30.  
  31. #ifdef SYSTEM_V
  32. #include <fcntl.h>
  33. #endif
  34. #include <signal.h>
  35.  
  36. #ifdef BSD
  37. #include "time.h"
  38. #include <sys/resource.h>
  39. #endif
  40.  
  41. static int check_status(int, char *, char *);
  42. static char *getsym(char *, char *);
  43. static void arg_dump();
  44. static int run_prog(char *, char **);
  45. static void delete_file(char *);
  46.  
  47. char   *argname;
  48. int     opts_cnt;
  49. char   *other_opts[20];
  50. char   *interface_opts[20];
  51. int     interface_cnt = 0;
  52. int    maxstatus = RC_SUCCESS; /* maximum exit status from called programs */
  53. int     exec_trace = 0;    /* set to print generated command lines */
  54.  
  55. /* names of executables to use if not defined by environment */
  56. #define FRONT_NAME "adafront"
  57. #define GEN_NAME "adagen"
  58. #define BND_NAME "adabind"
  59.  
  60. /* status_get extracts program exit code */
  61. #ifdef IBM_PC
  62. #define status_get(s)        (s)
  63. #define system_status_get(s) (s)
  64. #else
  65. #define status_get(s)           ((s)>>8)
  66. #define system_status_get(s) ((s) & 0xff)
  67. #endif
  68.  
  69. char   *base_name;
  70.  
  71. main(int argc, char **argv)
  72. {
  73.     int     c,fp;
  74.     int     status, ok = TRUE;
  75.     extern int  optind;
  76.     extern char *optarg;
  77.     char   *FRONT, *GEN, *BND; 
  78.     char   *arg_name;
  79.     char   *lib_name;
  80.     char   *list_name;
  81.     char   *source_name;
  82.     char   *msg_name;
  83.     char   *tmp_name;
  84.     char   *s_temp;
  85.     char   *l_name;
  86.     char   *basep;
  87.     int       prefix_len, base_len, suffix_len;
  88.     char   *lib_opt_str, *main_unit_name;
  89.     char   *object_files = "";
  90.     char   *front_options, *gen_options;
  91.     int     bind_opt = 0, main_opt = 0, save_msg_opt = 0 ;
  92.     int     list_opt = FALSE;   /* set to generate a listing */
  93.     char   *list_arg;        /* for passing list_opt to mrg */
  94.     int     lib_opt = FALSE;    /* set to TRUE if -l specified */
  95.     int     newlib_opt = FALSE; /* set to TRUE if -n specified */
  96.     int        time_limit = 15;    /* default time limit in minutes */
  97. #ifdef BSD
  98.     struct rlimit rlp;
  99. #endif
  100.  
  101. /* initializations */
  102.     arg_name = (char *) 0;
  103.     lib_name = (char *) 0;
  104.     front_options = "";
  105.     gen_options = "";
  106.  
  107. /*
  108.  * command options
  109.  *    -a        generated line number instructions
  110.  *    -b         bind the unit specified by 'm' option
  111.  *    -g        insert generated code into listing
  112.  *      -i              specify object files and libraries for pragma interface
  113.  *    -l libname    (old) library libname
  114.  *    -m main unit      specify the main binding unit.
  115.  *            or use default main unit
  116.  *    -n libname    new library libname
  117.  *      -s        create source program listing
  118.  *    -v        trace executed commands and exit status
  119.  *      -Y        save message files (for running B tests)
  120.  *      -P        compile predef
  121.  */
  122.  
  123. #ifdef IBM_PC
  124.     while((c = getopt(argc, argv, "AaBbGgL:l:M:m:NnSsVvYPi:")) != EOF) {
  125.           if (isupper(c)) c = tolower(c);
  126. #else
  127.     while((c = getopt(argc, argv, "abgl:m:nsvMPi:")) != EOF) {
  128. #endif
  129.     switch(c) {
  130.       case 'a':
  131.         s_temp = emalloc(strlen(gen_options) + 2);
  132.         strcpy(s_temp, gen_options);
  133.         strcat(s_temp, "l");
  134.         gen_options = s_temp;
  135.         break;
  136.       case 'b':
  137.         bind_opt = 1;
  138.         break;
  139.       case 'g':
  140.         s_temp = emalloc(strlen(gen_options) + 2);
  141.         strcpy(s_temp, gen_options);
  142.         strcat(s_temp, "g");
  143.         gen_options = s_temp;
  144.         break;
  145.       case 'l':
  146.         lib_opt = TRUE;
  147.         lib_name = emalloc(strlen(optarg) + 1);
  148.         strcpy(lib_name, optarg);
  149.         break;
  150.       case 'm':    
  151.         main_opt = 1;
  152.         main_unit_name = emalloc(strlen(optarg) + 1);
  153.         strcpy(main_unit_name, optarg);
  154.         break;
  155.       case 'n':
  156.         newlib_opt = TRUE;
  157.         break;
  158.       case 'i':
  159.         s_temp = emalloc(strlen(optarg) + 1);
  160.         strcpy(s_temp, optarg);
  161.         interface_opts[interface_cnt++] = s_temp;
  162.         break;
  163.       case 's':
  164.         list_opt++;
  165.         break;
  166.       case 'v':
  167.         exec_trace++;
  168.         break;
  169.       case 'Y':
  170.         save_msg_opt = TRUE ;
  171.         break;
  172.       case 'p':
  173.       case 'P':
  174.         s_temp = emalloc(strlen(front_options) + 2);
  175.         strcpy(s_temp, front_options);
  176.         strcat(s_temp, "p");
  177.         front_options = s_temp;
  178.         s_temp = emalloc(strlen(gen_options) + 2);
  179.         strcpy(s_temp, gen_options);
  180.         strcat(s_temp, "p");
  181.         gen_options = s_temp;
  182.         break;
  183.       case '?':
  184.         exit(RC_ABORT);
  185.         break;
  186.         default:
  187.         fprintf(stderr, "Unknown Option: %c\n", c);
  188.         exit(RC_ABORT);
  189.     }
  190.     }
  191.     if (optind < argc)
  192.     arg_name = argv[optind];
  193.     if (arg_name == (char *) 0) {
  194.     fprintf(stderr,"Invalid Usage: No ada file specified\n");
  195.     exit(RC_ABORT);
  196.     }
  197.     if (!lib_opt) { /* if -l not specified, try to get from environment */
  198.        lib_name = getenv("ADALIB");
  199.        if (lib_name!=(char *)0) {
  200.        lib_opt++;
  201.     }
  202.     if (lib_opt) {
  203.         printf("library defined by ADALIB: %s\n",lib_name);
  204.     }
  205.     }
  206.     if (!lib_opt) {
  207.        fprintf(stderr,
  208.         "Invalid Usage: please specify a library\n");
  209.        exit(RC_ABORT);
  210.     }
  211. #ifdef BSD
  212.     getrlimit(RLIMIT_CPU,&rlp);
  213.     (&rlp)->rlim_cur = time_limit*60;     /* limit to time_limit mins */
  214.     setrlimit(RLIMIT_CPU,&rlp);
  215. #endif
  216.  
  217.     basep = parsefile(arg_name, &prefix_len, &base_len, &suffix_len);
  218.     /* check for presence of ada file;  if none, make it ada */
  219.     if (suffix_len ==0) {
  220.     source_name = emalloc(strlen(arg_name) + 4 + 1);
  221.     strcpy(source_name, arg_name);
  222.     strcat(source_name, ".ada");
  223.     }
  224.     else {
  225.         source_name = arg_name;
  226.     }
  227.     base_name = emalloc(base_len + 1);
  228.     strncpy(base_name, basep, base_len);
  229.     if ((fp = open(source_name,O_RDONLY,0700)) < 0) {
  230.     fprintf(stderr,"Cannot access file %s\n",source_name);
  231.     exit(RC_ABORT);
  232.     }
  233.     close(fp);
  234.  
  235. #ifdef MONITOR
  236.     
  237.     {
  238.     FILE *fp;
  239.     fp = fopen( "CWKLIB.$$$", "w" );
  240.     fprintf( fp, "%s\n", source_name );
  241.     fclose(fp);
  242.     }
  243.  
  244. #endif
  245.  
  246.     if (newlib_opt){
  247.         if (exec_trace) {
  248.         fprintf(stderr, "mkdir %s ", lib_name);
  249.         }
  250.         status = mkdir(lib_name, 0777);
  251.         if (exec_trace) {
  252.         fprintf(stderr, " ? %d\n", status);
  253.         }
  254.     }
  255.     status = 0;
  256.     if (status) {
  257.         fprintf(stderr,"%s cannot be used as a library\n", lib_name);
  258.         exit(RC_ABORT);
  259.     }
  260.     if (!newlib_opt) {
  261.         /* check for presence of library file */
  262.     l_name = emalloc(strlen(lib_name) + strlen(LIBFILENAME) + 2);
  263.     strcpy(l_name, lib_name);
  264.  
  265. #ifdef BSD
  266.     strcat(l_name, "/");
  267. #endif
  268. #ifdef SYSTEM_V
  269.     strcat(l_name, "/");
  270. #endif
  271. #ifdef IBM_PC
  272.     strcat(l_name, "/");
  273. #endif
  274.     strcat(l_name, LIBFILENAME);
  275.  
  276.         if ((fp = open(l_name,O_RDONLY,0700)) < 0) {
  277.             fprintf(stderr,"%s cannot be used as a library\n", lib_name);
  278.             exit(RC_ABORT);
  279.         }
  280.     efree(l_name);
  281.         close(fp);
  282.     }
  283.  
  284.     /* format library option as expected by adafront & adagen */
  285.     lib_opt_str = ((newlib_opt) ? "-nl" : "-l");
  286.  
  287.     FRONT = getsym("ADAFRONT", FRONT_NAME);
  288.     other_opts[opts_cnt = 0] = FRONT;
  289.     if (strlen(front_options) != 0) {
  290.         other_opts[++opts_cnt] = "-s";
  291.         other_opts[++opts_cnt] = front_options;
  292.     }
  293.     other_opts[++opts_cnt] = lib_opt_str;
  294.     other_opts[++opts_cnt] = lib_name;
  295.     other_opts[++opts_cnt] = source_name;
  296.     other_opts[++opts_cnt] = (char *) 0;
  297.     if (exec_trace)
  298.         arg_dump();
  299.     status = run_prog(FRONT, other_opts);
  300.     if (exec_trace)
  301.         fprintf(stderr, " ? %d\n", status);
  302.     ok = check_status(status, "FRONT", arg_name);
  303.         /* check for front end errors (adafront will exit with RC_ERRORS) */
  304.     if (status_get(status)== RC_ERRORS)
  305.         ok = FALSE;
  306.  
  307.     if (ok) {
  308.         GEN = getsym("GEN", GEN_NAME);
  309.         other_opts[opts_cnt = 0] = GEN;
  310.         if (strlen(gen_options) != 0) {
  311.             other_opts[++opts_cnt] = "-g";
  312.             other_opts[++opts_cnt] = gen_options;
  313.         }
  314.         other_opts[++opts_cnt] = lib_opt_str;
  315.         other_opts[++opts_cnt] = lib_name;
  316.         other_opts[++opts_cnt] = base_name;
  317.         other_opts[++opts_cnt] = (char *) 0;
  318.         if (exec_trace)
  319.             arg_dump();
  320.         status =  run_prog(GEN, other_opts);
  321.         if (exec_trace)
  322.             fprintf(stderr, " ? %d\n", status);
  323.         ok = check_status(status, "GEN", arg_name);
  324.     }
  325.  
  326.     if (ok && bind_opt) { /* run binder if desired */
  327.         BND = getsym("BND", BND_NAME);
  328.         other_opts[opts_cnt = 0] = BND;
  329.         other_opts[++opts_cnt] = "-c"; /* indicate errors in message form */
  330.         other_opts[++opts_cnt] = base_name; /* pass filename for msg listing */
  331.  
  332.         while(interface_cnt) {
  333.             other_opts[++opts_cnt] = "-i";
  334.             other_opts[++opts_cnt] = interface_opts[--interface_cnt];
  335.         }
  336.         if (main_opt) {
  337.             other_opts[++opts_cnt] = "-m";
  338.             other_opts[++opts_cnt] = main_unit_name;
  339.         }
  340.         other_opts[++opts_cnt] = lib_name; /* library is current directory */
  341.         other_opts[++opts_cnt] = (char *) 0;
  342.         if (exec_trace)
  343.             arg_dump();
  344.         status =  run_prog(BND, other_opts);
  345.         if (exec_trace)
  346.             fprintf(stderr, " ? %d\n", status);
  347.         ok = check_status(status, "BND", arg_name);
  348.     }
  349. #ifdef IBM_PC
  350.     list_name = emalloc(strlen(base_name) + 4 + 1);
  351.     strcpy(list_name, base_name);
  352.     strcat(list_name, ".lis");
  353. #endif
  354. #ifdef SYSTEM_V
  355.     list_name = emalloc(strlen(base_name) + 4 + 1);
  356.     strcpy(list_name, base_name);
  357.     strcat(list_name, ".lis");
  358. #endif
  359. #ifdef BSD
  360.     list_name = emalloc(strlen(base_name) + 4 + 1);
  361.     strcpy(list_name, base_name);
  362.     strcat(list_name, ".lis");
  363. #endif
  364.     list_arg = (list_opt>0) ? "1" : "0";
  365.     msg_name = emalloc(strlen(lib_name) + strlen(base_name) + 7);
  366.     strcpy(msg_name, lib_name);
  367. #ifdef BSD
  368.     strcat(msg_name,"/");
  369. #endif
  370. #ifdef SYSTEM_V
  371.     strcat(msg_name,"/");
  372. #endif
  373. #ifdef IBM_PC
  374.     strcat(msg_name,"/");
  375. #endif
  376.     strcat(msg_name, base_name);
  377.     strcat(msg_name, ".msg");
  378.     status = mrg(source_name,msg_name, list_name, list_arg);
  379.     efree(list_name);
  380.     if (!save_msg_opt) {
  381.         delete_file(msg_name);
  382.     efree(msg_name);
  383.     }
  384.  
  385.     exit(maxstatus);
  386. }
  387.  
  388. static char *getsym(char *env_name, char *def_value)        /*;getsym*/
  389. {
  390.   /* Retrieve environment variable designating the executable module for
  391.    * a given phase of the compiler.
  392.    * If the variable is not defined, a default is supplied for BSD systems.
  393.    */
  394.     char   *s;
  395.  
  396.     s = getenv(env_name);
  397.     if (s==(char *)0) {
  398.         char *t = get_libdir();
  399.         s = emalloc(strlen(t) + strlen(def_value) + 2);
  400.         sprintf(s,"%s/%s", t, def_value);
  401.     }
  402.     return s;
  403. }
  404.  
  405. static int check_status(int pstatus, char *phase, char *filename)
  406.                                                             /*;check_status*/
  407. {
  408.  
  409. #ifdef BSD
  410.     if (system_status_get(pstatus) == SIGXCPU) {
  411.         fprintf(stderr, "Ada/Ed cpu time limit exceeded for %s\n",phase);
  412.         return (FALSE);
  413.     }
  414. #endif
  415.  
  416.     /* check for internal compiler error and a signal (system transmitted)
  417.      * that is not IGNORE (1) or BAD_SIGNAL (-1)
  418.      * Check first for crash, since have no guarantee what will appear
  419.      * in 'user' section of return code (status_get field)
  420.      */
  421.     if ( (status_get(pstatus)  == RC_INTERNAL_ERROR)
  422.       || (system_status_get(pstatus) > 1 && system_status_get(pstatus) < 255)) {
  423.         maxstatus = RC_INTERNAL_ERROR;
  424.         fprintf(stderr,"Ada/Ed Internal error(%s) for %s\n", phase, filename);
  425.         return (FALSE);
  426.     }
  427.     if (status_get(pstatus)  == RC_SUCCESS) {
  428.         return (TRUE);
  429.     }
  430.     if (status_get(pstatus) == RC_ERRORS){
  431.         maxstatus = RC_ERRORS;
  432.         return (TRUE);
  433.     }
  434.     if (status_get(pstatus)  == RC_ABORT) {
  435.         maxstatus = RC_ABORT;
  436.         return (FALSE);
  437.     }
  438. }
  439.  
  440. static void arg_dump()                                            /*;arg_dump*/
  441. {
  442.     /*list generated command*/
  443.     int     i;
  444.     fprintf(stderr, "%s ", other_opts[0]);
  445.     for (i = 1; i < opts_cnt; i++) {
  446.         fprintf(stderr, " %s", other_opts[i]);
  447.     }
  448.     fprintf(stderr,"\n");
  449. }
  450.  
  451. static int run_prog(char *prog, char **args)                    /*;run_prog*/
  452. {
  453.     int status;
  454.  
  455. #ifdef IBM_PC
  456.     status = spawnv(P_WAIT, prog, args);
  457. #else
  458.     if (fork() == 0)
  459.         if (execvp(prog , other_opts)) {
  460.             fprintf(stderr,"cannot execute %s\n", prog);
  461.             exit(RC_ABORT);
  462.         }
  463.     wait( WAITPARM &status);
  464. #endif
  465.     return status;
  466. }
  467.  
  468. static void delete_file(char *file_name)                    /* ;delete_file */
  469. {
  470.     int status;
  471.  
  472.     status = unlink(file_name);
  473.     if (exec_trace)
  474.         fprintf(stderr,"unlink %s ? %d\n",file_name, status);
  475. }
  476.